//Copyright (c) 1998-2006 Core Solutions Limited. All rights reserved.
//============================================================================
//CURRENT VERSION iDEX.3.7.0.013
//============================================================================
//CHANGE LOG
//iDEX.3.7.0.013 : Feb 2, 2006, Ric YIK, File Created
//============================================================================

package com.erp.common.web.multirow;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.erp.app.util.web.WebUtil;
import com.erp.common.web.ActionMethodDispatcher;
import com.erp.common.web.RemarkTextPopup;
import com.erp.common.web.SelectRemarkTextAction;
import com.erp.common.web.SimpleBaseActionDispatcher;
import com.erp.framework.SimpleConstants;
import com.erp.framework.controller.action.SimpleMaintStyleAction;
import com.erp.framework.controller.action.SimpleMaintStyleActionTemplate;
import com.erp.framework.model.pk.SimpleBasePk;
import com.erp.framework.util.CommonUtil;
import com.erp.framework.util.logger.Logger;

/**
 * An action class for handling the screen flow which MultiRows may be edit in 
 * a seperate screen like a header.
 * 
 * <pre>
 * Unlike SimpleMaintStyleAction, this class handles the screen flow which requires
 * the MultiRows to be edited like a header.
 * 
 * The screen flow of updating a multirow is seperated into 2 steps:
 * 
 * 1. When a multirow is selected, a pageEvent named "updating&lt;&lt;MultiRowName&gt;&gt;" 
 *    is issued. With respect to the current folderIdx of the screen, a 
 *    corresponding MultiRow is created, with it's isEditingRow as true. The 
 *    last pageEvent for this folder is also stored. With the isEditingRow flag,
 *    the JSP logic will show the editor of the current editing MultiRow of 
 *    that folder.
 *
 * 2. When the user finished editing the MultiRow and want to return to the 
 *    MultiRow listing screen. the user may issue a event named 
 *    "update&lt;&lt;MultiRowName&gt;&gt;". The isEditingRow flag of the current MultiRow 
 *    will be set as false.
 * 
 * Similarly, the screen flow of creating a multirow is seperated into 2 steps:
 * 
 * 1. When a user wants to create a new MultiRow, a pageEvent named 
 *    "adding&lt;&lt;MultiRowName&gt;&gt;" is issued. The corresponding MultiRow will be 
 *    created and added to the corresponding MultiRow list. The isEditingRow of 
 *    this adding row will be marked as true, and the RowMode will be makred as "Creating".
 * 
 * 2. When the user finished the data entry and wants to return to the MultiRow 
 *    listing screen, the user may issue an event named "add&lt;&lt;MultiRowName&gt;&gt;". 
 *    The isEditingRow flag of the current MultiRow will be set to false.
 * 
 * In contract to the "conventional" implementation of the similar flows, which duplicates
 * the fields of the current editing row as temporary variables into the header part
 * of the MaintenanceForm and requires copying of data from the temporary variables 
 * to the actual MultiRow, this class enables direct editing of MultiRow such that no 
 * duplication of MultiRow fields are required. This advantage is achieved with 
 * collaborations of the following classes:
 * 
 * SimpleMaintMulitRowForm: Maintains the current editing row and the pageEvent for 
 * each folder.
 * 
 * SimpleMaintMultiRowList: Exposes Javabean-compliant getter/setters of a list of 
 * MultiRows such that the Struts's &lt;bean&gt; tags can directly access any MultiRow at 
 * a partular position of a MultiRow List. For example:
 * 
 * &lt;%
 * int custFolderIdx = custMaintenanceForm.getFolderIdxAsIntInternal();
 * int custCurrentRowIdx = custMaintenanceForm.getCurrentRowIdx();
 * String currentRow = "customerMultiRows[" + custFolderIdx + "].multiRow[" + custCurrentRowIdx + "]";
 * String custCode = currentRow + ".custCode";
 * String addressCode = currentRow + ".addressCode";
 * %&gt;
 * &lt;bean:write name="custMaintenanceForm" property="&lt;%=custCode%&gt;" /&gt;
 * &lt;html:text property="&lt;%=addressCode%&gt;" styleClass="textbox1"/&gt;
 * 
 * As a MultiRow is always inside a MultiRow list, the user is not required to 
 * trigger the "add&lt;&lt;MultiRowName&gt;&gt;" and "update&lt;&lt;MultiRowName&gt;&gt;" to persist the
 * current editing MultiRow into the database. This is another advantage gained 
 * over the "conventional" implementation.
 * 
 * This class handles a set of pageEvents and dispatches the event to the corresponding 
 * handler, by the following rules:
 * 
 * 1. If the value pageEvent starts with one of the following PageEventPrefixes: 
 *    { ACTION_ADDING, ACTION_ADD, ACTION_UPDATING, ACTION_UPDATE, ACTION_DELETE, ACTION_CANCEL_ADDING, ACTION_CANCEL_UPDATING, ACTION_SPEDIT }
 *    Dispatch to this.processAction&lt;&lt;PageEventPrefix&gt;&gt;(mapping, formIn, request, response, errors).
 *
 * 2. Otherwise, dispatch to this.processAction&lt;&lt;PageEvent&gt;&gt;(mapping, formIn, request, response, errors).
 *    ActionMethodDispatcher is used to achieve this.
 * 
 * With rule 2, all subclasses of this class can handle the pageEvent without 
 * overriding / modifying the handlePageEvent method.
 * 
 * Example modules: Customer Master, Vendor Master
 * </pre>
 * 
 * @author Ric YIK
 * 
 * @see com.erp.common.web.multirow.SimpleMaintMultiRowForm
 * @see com.erp.common.web.multirow.SimpleMaintMultiRowList
 * @see com.erp.common.web.multirow.SimpleMaintMulitRow
 */
public abstract class SimpleMaintMultiRowAction extends SimpleMaintStyleActionTemplate {

    public static final String ACTION_ADDING = "adding";

    public static final String ACTION_ADD = "add";

    public static final String ACTION_CANCEL_ADDING = "cancelAdding";

    public static final String ACTION_UPDATING = "updating";

    public static final String ACTION_UPDATE = "update";

    public static final String ACTION_CANCEL_UPDATING = "cancelUpdating";

    public static final String ACTION_DELETE = "delete";

    public static final String ACTION_SPEDIT = SimpleConstants.ACTION_SPEDIT;

    public static final String STATUS_SPSET = SelectRemarkTextAction.STATUS_SP_SET;

    // //////////////////////////////////////////////////////////////////////////////
    // LOGICAL AND BUSINESS METHODS
    // //////////////////////////////////////////////////////////////////////////////

    public ActionForward handlePageEvent(ActionMapping mapping, ActionForm formIn, 
            HttpServletRequest request, HttpServletResponse response, ActionErrors errors) {
        final ActionForward defaultActionForward = new ActionForward(mapping.getInput());
        final SimpleMaintMultiRowForm form = (SimpleMaintMultiRowForm) formIn;
        ActionForward actionForward = defaultActionForward;
        if (this.isHandled(request)) {
            return actionForward;
        }
        // Dispatch by method name
        actionForward = new ActionMethodDispatcher()
            .setAction(this)
            .setDefaultActionForward(actionForward)
            .setNextDispatcher(new SimpleBaseActionDispatcher() {

                public ActionForward processAction(String pageEvent, ActionMapping mapping, ActionForm formIn, HttpServletRequest request, HttpServletResponse response, ActionErrors errors) {
                    if (form.getPageEvent().startsWith(ACTION_SPEDIT)) {
                        return processActionSpEdit(mapping, formIn, request, response, errors);
                    } else if (form.getPageEvent().startsWith(ACTION_ADDING)) {
                        return processActionAdding(mapping, formIn, request, response, errors);
                    } else if (form.getPageEvent().startsWith(ACTION_ADD)) {
                        return processActionAdd(mapping, formIn, request, response, errors);
                    } else if (form.getPageEvent().startsWith(ACTION_UPDATING)) {
                        return processActionUpdating(mapping, formIn, request, response, errors);
                    } else if (form.getPageEvent().startsWith(ACTION_UPDATE)) {
                        return processActionUpdate(mapping, formIn, request, response, errors);
                    } else if (form.getPageEvent().startsWith(ACTION_DELETE)) {
                        return processActionDelete(mapping, formIn, request, response, errors);
                    } else if (form.getPageEvent().startsWith(ACTION_CANCEL_ADDING)) {
                        return processActionCancelAdding(mapping, formIn, request, response, errors);
                    } else if (form.getPageEvent().startsWith(ACTION_CANCEL_UPDATING)) {
                        return processActionCancelUpdating(mapping, formIn, request, response, errors);
                    } else {
                        return defaultActionForward;
                    }
                }

            })
            .processAction(form.getPageEvent(), mapping, formIn, request, response, errors);
        if (!form.getPageEvent().equals("doNothing")) {
            form.setLastPageEvent(form.getPageEvent());
        }
        this.saveToken(request);
        this.setHandled(request);
        return actionForward;
    }

//    protected ActionForward processOtherStatus(ActionMapping mapping, ActionForm formIn, 
//            HttpServletRequest request, HttpServletResponse response, ActionErrors errors, String rb_status) {
//        ActionForward actionForward = new ActionForward(mapping.getInput());
//        if (rb_status.startsWith(STATUS_SPSET)) {
//            actionForward =  this.processStatusSpSet(mapping, formIn, request, response, errors, rb_status);
//        }
//        return actionForward;
//    }
//
//    protected ActionForward processStatusSpSet(ActionMapping mapping, ActionForm formIn, 
//            HttpServletRequest request, HttpServletResponse response, ActionErrors errors, String rb_status) {
//        RemarkTextPopup popup = new RemarkTextPopup(request.getSession(false)).retrieveValues();
//        SimpleMaintMultiRowForm form = (SimpleMaintMultiRowForm) formIn;
//        form.retrieveRemarkTextPopupValues(popup);
//        return new ActionForward(mapping.getInput());
//    }

//    protected ActionForward processActionSpEdit(ActionMapping mapping, ActionForm formIn, 
//            HttpServletRequest request, HttpServletResponse response, ActionErrors errors) {
//        RemarkTextPopup popup = new RemarkTextPopup(request.getSession(false));
//        popup.setSelectRemarkText(true);
//        popup.setSessionName(this.getSessionSimpleMaintStatus());
//        popup.setOpenerPath(this.getFunctionId());
//        SimpleMaintMultiRowForm form = (SimpleMaintMultiRowForm) formIn;
//        popup.setPageEventSrc(form.getPageEventSrc());
//        popup.setFieldId(CommonUtil.nullToString(form.getPageEvent()).substring(ACTION_SPEDIT.length()));
//        form.setRemarkTextPopupValues(popup);
//        popup.build();
//        return new ActionForward(mapping.getInput());
//    }

    protected ActionForward processActionAdding(ActionMapping mapping, ActionForm formIn, 
            HttpServletRequest request, HttpServletResponse response, ActionErrors errors) {
        SimpleMaintMultiRowForm form = (SimpleMaintMultiRowForm) formIn;
        ActionForward actionForward = new ActionForward(mapping.getInput());
        try {
            form.startAddingRow(mapping, formIn, request, response, errors, actionForward);
        } catch (Exception e) {
            Logger.log(this, e);
        }

        return actionForward;
    }

    protected ActionForward processActionAdd(ActionMapping mapping, ActionForm formIn, 
            HttpServletRequest request, HttpServletResponse response, ActionErrors errors) {
        SimpleMaintMultiRowForm form = (SimpleMaintMultiRowForm) formIn;
        ActionForward actionForward = new ActionForward(mapping.getInput());
        try {
            actionForward = form.finishAddingRow(mapping, formIn, request,
                    response, errors, actionForward);
        } catch (Exception e) {
            Logger.log(this, e);
        }

        return actionForward;
    }

    protected ActionForward processActionUpdating(ActionMapping mapping, ActionForm formIn, 
            HttpServletRequest request, HttpServletResponse response, ActionErrors errors) {
        SimpleMaintMultiRowForm form = (SimpleMaintMultiRowForm) formIn;
        ActionForward actionForward = new ActionForward(mapping.getInput());
        try {
            form.startUpdatingRow(mapping, formIn, request, response, errors, actionForward);
        } catch (Exception e) {
            Logger.log(this, e);
        }

        return actionForward;
    }

    protected ActionForward processActionUpdate(ActionMapping mapping, ActionForm formIn, 
            HttpServletRequest request, HttpServletResponse response, ActionErrors errors) {
        SimpleMaintMultiRowForm form = (SimpleMaintMultiRowForm) formIn;
        ActionForward actionForward = new ActionForward(mapping.getInput());
        try {
            actionForward = form.finishUpdatingRow(mapping, formIn, request, response, errors, actionForward);
        } catch (Exception e) {
            Logger.log(this, e);
        }

        return actionForward;
    }

    protected ActionForward processActionDelete(ActionMapping mapping, ActionForm formIn, 
            HttpServletRequest request, HttpServletResponse response, ActionErrors errors) {
        SimpleMaintMultiRowForm form = (SimpleMaintMultiRowForm) formIn;
        ActionForward actionForward = new ActionForward(mapping.getInput());
        try {
            form.deleteCurrentRow();
        } catch (Exception e) {
            Logger.log(this, e);
        }

        return actionForward;
    }

    ////////////////////////////////////////////////////////////////////////////////
    // IMPLEMENTS PARENT'S ABSTRACT METHODS
    ////////////////////////////////////////////////////////////////////////////////

    protected SimpleBasePk getPk(ActionForm formIn, HttpServletRequest request) {
        SimpleMaintMultiRowForm form = (SimpleMaintMultiRowForm) formIn;
        return form.makePk(WebUtil.getAppropriateCompanyCode(request.getSession(false), this.getSpShareParamId(formIn, request)));
    }

    protected abstract String getSpShareParamId(ActionMapping mapping, ActionForm formIn, 
            HttpServletRequest request, HttpServletResponse response, ActionErrors errors);

    protected String getSpShareParamId() {
        return this.getSpShareParamId(null, null, null, null, null);
    }

    protected String getSpShareParamId(ActionForm formIn, HttpServletRequest request) {
        return this.getSpShareParamId(null, formIn, request, null, null);
    }

    protected ActionForward processActionCancelAdding(ActionMapping mapping,
            ActionForm formIn, HttpServletRequest request,
            HttpServletResponse response, ActionErrors errors) {
        SimpleMaintMultiRowForm form = (SimpleMaintMultiRowForm) formIn;
        ActionForward actionForward = new ActionForward(mapping.getInput());
        try {
            form.cancelAddingRow(mapping, formIn, request, response, errors, actionForward);
        } catch (Exception e) {
            Logger.log(this, e);
        }

        return actionForward;
    }

    protected ActionForward processActionCancelUpdating(ActionMapping mapping,
            ActionForm formIn, HttpServletRequest request, HttpServletResponse response, ActionErrors errors) {
        SimpleMaintMultiRowForm form = (SimpleMaintMultiRowForm) formIn;
        ActionForward actionForward = new ActionForward(mapping.getInput());
        try {
            form.cancelUpdatingRow(mapping, formIn, request, response, errors, actionForward);
        } catch (Exception e) {
            Logger.log(this, e);
        }

        return actionForward;
    }

    public abstract String getSessionNameOfUpdatingOriginalRow();

    ////////////////////////////////////////////////////////////////////////////////
    // END OF LOGICAL AND BUSINESS METHODS
    ////////////////////////////////////////////////////////////////////////////////

}
